package com.stox.ui.javafx.core.widget;

import java.util.HashMap;
import java.util.Map;

import javafx.event.EventHandler;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.DataFormat;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import lombok.Delegate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.stox.dto.AbstractModel;
import com.stox.dto.intf.AbstractModelSearchable;
import com.stox.event.AbstractModelSelectionEvent;
import com.stox.ui.javafx.core.model.TreeViewAbstractModelSearchable;

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AbstractModelTreeView extends TreeView<AbstractModel> implements AbstractModelSearchable {
	private static final long serialVersionUID = 1L;
	
	@Autowired
	private ApplicationContext applicationContext;
	
	@Delegate
	private TreeViewAbstractModelSearchable abstractModelSearchable = new TreeViewAbstractModelSearchable(this);
	
	private static EventHandler<DragEvent> dragDoneEventHandler = new EventHandler<DragEvent>(){
		@Override
		public void handle(DragEvent event) {
			System.out.println("---------------Drag Completed----------------");
			System.out.println("GestureSource : "+event.getGestureSource());
			System.out.println("GestureTarget : "+event.getGestureTarget());
			System.out.println("Source : "+event.getSource());
			System.out.println("Target : "+event.getTarget());
		}
	};
	
	private static EventHandler<KeyEvent> keyEventHandler = new EventHandler<KeyEvent>(){
		@Override
		public void handle(KeyEvent event) {
			if(KeyCode.ENTER.equals(event.getCode())){
				AbstractModelTreeView treeView = (AbstractModelTreeView)event.getSource();
				treeView.publishAbstractModelSelectionEvent();
			}
		}
	};
	
	private static EventHandler<MouseEvent> mouseEventHandler = new EventHandler<MouseEvent>(){
		@Override
		public void handle(MouseEvent event) {
			AbstractModelTreeView treeView = (AbstractModelTreeView)event.getSource();
			if(MouseButton.SECONDARY.equals(event.getButton())){
				ContextMenu contextMenu = treeView.getContextMenu();
				if(null != contextMenu){
					contextMenu.show(treeView, event.getSceneX(), event.getSceneY());
				}
			}else if(MouseButton.PRIMARY.equals(event.getButton())){
				if(2 == event.getClickCount()){
					treeView.publishAbstractModelSelectionEvent();
				}
			}
		}
	};
	
	private static EventHandler<MouseEvent> dragDetectedEventHandler = new EventHandler<MouseEvent>(){
		@Override
		public void handle(MouseEvent event) {
			AbstractModelTreeView treeView = (AbstractModelTreeView)event.getSource();
			Dragboard db = treeView.startDragAndDrop(TransferMode.ANY);
			
			Map<DataFormat, Object> map = new HashMap<DataFormat,Object>(1);
			map.put(DataFormat.PLAIN_TEXT, "Dummy Value - Not really needed");
			db.setContent(map);
			
			SnapshotParameters snapshotParameters = new SnapshotParameters();
			snapshotParameters.setFill(Color.TRANSPARENT);
			
			VBox box = new VBox();
			for(TreeItem<AbstractModel> treeItem : treeView.getSelectionModel().getSelectedItems()){
				Text text = new Text(treeItem.getValue().getName());
				text.setFill(Color.WHITE);
				text.setFont(Font.font(20));
				box.getChildren().add(text);
			}
			db.setDragView(box.snapshot(snapshotParameters, null));
		}
	};
	
	public AbstractModelTreeView() {
		setOnDragDetected(dragDetectedEventHandler);
		setOnDragDone(dragDoneEventHandler);
		addEventFilter(KeyEvent.KEY_PRESSED, keyEventHandler);
		addEventFilter(MouseEvent.MOUSE_PRESSED, mouseEventHandler);
	}
	
	private void publishAbstractModelSelectionEvent(){
		applicationContext.publishEvent(new AbstractModelSelectionEvent(this));
	}
	
}
